#include <functional>
#include <future>
#include <iostream>
#include <memory>
#include <thread>
#include <unordered_map>
#include <vector>
#include <unistd.h>

class TimerTask
{
public:
    using TaskFunc = std::function<void()>; 
    using ReleaseFunc = std::function<void()>;
    TimerTask(uint64_t id, uint32_t delay, const TaskFunc &task):_id(id), _timeout(delay), _task(task), _canceled(false)
    {}
    ~TimerTask() 
    {
        if (!_canceled) _task();
        _release();
    }
    void setRealease(const ReleaseFunc &release) {_release = release;}
    uint32_t DelayTime() {return _timeout;}
    void Cancel() {_canceled = true;}
private:
    uint64_t _id; //定时任务对象id
    uint32_t _timeout; //定时任务的超时时间
    TaskFunc _task; //定时器对象执行的定时任务
    ReleaseFunc _release; //删除TimerWheel保存的定时器对象信息
    bool _canceled;
};

class TimerWheel
{
public:
    TimerWheel():_ticket(0), _capacity(60), _wheel(_capacity)
    {}
    void TimerAdd(const uint64_t id, const uint32_t delay, const TimerTask::TaskFunc &cb)   //添加定时任务
    {
        PtrTask pt(new TimerTask(id, delay, cb));
        pt->setRealease(std::bind(&TimerWheel::RemoveTimer, this, id));
        int pos = (delay + _ticket) % _capacity;
        _wheel[pos].emplace_back(pt);
        _times.insert({id, WeakTask(pt)});
    }
    void TimerReflash(uint64_t id)  //刷新定时任务
    {
        auto it = _times.find(id);
        if(it == _times.end())
        {
            //没找到对应任务，直接返回
            return;
        }
        PtrTask pt = it->second.lock(); //获取weak_ptr管理的share_ptr
        int delay = pt->DelayTime();
        int pos = (delay + _ticket) % _capacity;
        _wheel[pos].emplace_back(pt);
    }
    void TimerCancel(const uint64_t &id)
    {
        auto it = _times.find(id);
        if(it == _times.end())
        {
            //没找到对应任务，直接返回
            return;
        }
        PtrTask pt = it->second.lock(); 
        if(pt)  pt->Cancel();
    }
    //应每秒被执行一次
    void RunTimerTask()
    {
        _ticket = (_ticket + 1) % _capacity;
        _wheel[_ticket].clear();   //执行析构
    }
private:
    void RemoveTimer(uint64_t id)
    {
        auto it = _times.find(id);
        if(it != _times.end())
            _times.erase(it);
    }
private:
    using WeakTask = std::weak_ptr<TimerTask>;
    using PtrTask = std::shared_ptr<TimerTask>;
    int _ticket;    //秒表，走到哪释放哪
    int _capacity;  //最大延迟时间
    std::vector<std::vector<PtrTask>> _wheel;
    std::unordered_map<uint64_t, WeakTask> _times;
};


class Test
{
public:
    Test()  {std::cout<<"构造\n";}
    ~Test()  {std::cout<<"析构\n";}
};

void delTest(Test* t)
{
    delete t;
}
int main()
{
    Test* t = new Test();

    TimerWheel tw;
    tw.TimerAdd(888, 5, std::bind(delTest, t));

    int i = 5;
    while(i--)
    {
        tw.TimerReflash(888);
        //移动秒表
        tw.RunTimerTask();
        std::cout<< "刷新定时任务，5秒后执行\n";
        sleep(1);
    }
    // while(1)
    // {
    //     std::cout<< "-------------\n";
    //     tw.RunTimerTask();
    //     sleep(1);
    // }
}
